namespace ClassyBlog.Infrastructure.Specs.Unit
{
    using System;

    using Machine.Specifications;
    using NSubstitute;

    using DataAccess;
    using DomainObjects;

    [Subject(typeof(CurrentBlogProvider))]
    public class when_creating_current_blog_provider_with_null_repository
    {
        static Exception exception;

        Because of = () => exception =
            Catch.Exception(() => new CurrentBlogProvider(null));

        It should_throw_exception = () =>
            exception.ShouldBeOfType<ArgumentNullException>();
    }

    [Subject(typeof(CurrentBlogProvider))]
    public class when_current_blog_is_accessed_for_first_time
    {
        static IBlogRepository repository;
        static CurrentBlogProvider provider;

        Establish context = () =>
        {
            repository = Substitute.For<IBlogRepository>();
            repository.One().Returns(ObjectMother.CreateBlog());

            provider = new CurrentBlogProvider(repository);
        };

        Because of = () => { var blog = provider.Current; };

        It should_use_repository_to_reterive_the_blog = () =>
            repository.Received().One();
    }

    [Subject(typeof(CurrentBlogProvider))]
    public class when_current_blog_is_accessed_for_consequent_times
    {
        static IBlogRepository repository;
        static CurrentBlogProvider provider;
        static int callCount;
        static Blog blog;

        Establish context = () =>
        {
            callCount = 0;
            repository = Substitute.For<IBlogRepository>();
            repository.One().Returns(c =>
            {
                callCount++;
                return ObjectMother.CreateBlog();
            });

            provider = new CurrentBlogProvider(repository);
        };

        Because of = () =>
        {
            blog = provider.Current;
            blog = provider.Current;
            blog = provider.Current;
        };

        It should_return_the_reterived_blog = () => callCount.ShouldEqual(1);
    }
}